//	CP2013 Traffic Simulator Assignment
//      Traffic Model
//	Java version
//      Coded by Matthew Johnson

package traffic;
import java.util.Vector;

//Stores all the elements of the simulation
public class Model {
    //A map of all the tiles in the model and their current direction
    public TileMap map;
    //The intersection
    public Intersection intSct;
    //The entry and exit roads
    public Road nRoad, eRoad, sRoad, wRoad;
    public Road[] roads;
    //The settings for the simulation
    public SimulationParams settings;
    //The vehicles
    public Vector<Vehicle> vehicles;

    //Constructor: sets up the simulation with provided settings
    Model(SimulationParams setup)
    {
        
	//Copy the setup parameters into our settings
	settings = setup;

        //For now green length is set to default
        setup.greenLength = Intersection.DEFAULT_GREEN_LENGTH;

        //Create the intersection
        intSct = new Intersection(settings.nsLanes, settings.ewLanes);
        //Setup the anchor point
	intSct.setAnchor(new Coordinate(Lane.DEFAULT_LENGTH, Lane.DEFAULT_LENGTH));

        //Create the Vehicle Vector
        vehicles = new Vector<Vehicle>();

	//Setup Road Array and explicit references to each road
	roads = new Road[4];
	roads[0] = nRoad = new Road();
	roads[1] = sRoad = new Road();
	roads[2] = eRoad = new Road();
	roads[3] = wRoad = new Road();

	//Create the NS lanes
	for (int i = 0; i < settings.nsLanes; i++)
	{
            //Both lanes hold Northbound traffic and have the same length, only difference is probability
		//For outgoing lanes, no vehicles will be spawned
		nRoad.lanes.add(new Lane(Lane.DEFAULT_LENGTH, Direction.NORTH, 0));

		//Incoming lanes spawn vehicles
		sRoad.lanes.add(new Lane(Lane.DEFAULT_LENGTH,Direction.NORTH, settings.nsProb));
	}

	//Create the WE lanes
	for (int i = 0; i < settings.ewLanes; i++)
	{
            //Both lanes hold Northbound traffic and have the same length, only difference is probability
		//For outgoing lanes, no vehicles will be spawned
		eRoad.lanes.add(new Lane(Lane.DEFAULT_LENGTH,Direction.EAST, 0));

		//Incoming lanes spawn vehicles
		wRoad.lanes.add(new Lane(Lane.DEFAULT_LENGTH,Direction.EAST, settings.ewProb));
	}

        //Setup the anchor points for the lanes
	//North road
	for (int i = 0; i < nRoad.lanes.size(); i++)
	{
		//Lanes start at the top of the screen and go down to the intersection
		Coordinate c = new Coordinate(intSct.getAnchor().x + i, 0);

		//The spawn point is the the anchor
		Coordinate s = new Coordinate(c);

		//The intersection entry point is the opposite end to the anchor
		Coordinate ie = new Coordinate(c);
		ie.y += (sRoad.lanes.get(i).length - 1);

		//Set the anchor, spawn point, and intersection entry point
		nRoad.lanes.get(i).anchor = c;
		nRoad.lanes.get(i).spawnPoint = s;
		nRoad.lanes.get(i).intersectionEntryPoint = ie;
	}

	//South road
	for (int i = 0; i < sRoad.lanes.size(); i++)
	{
		//Lanes start at the bottom of the intersection and go down to the bottom of the screen
		Coordinate c = new Coordinate(intSct.getAnchor().x + i,
                        intSct.getAnchor().y + intSct.getHeight());

		//The spawn point is the opposite end to the anchor
		Coordinate s = new Coordinate(c);
		s.y += (sRoad.lanes.get(i).length - 1);

		//The intersection entry point is the anchor
		Coordinate ie = new Coordinate(c);

		//Set the anchor, spawn point, and intersection entry point
		sRoad.lanes.get(i).anchor = c;
		sRoad.lanes.get(i).spawnPoint = s;
		sRoad.lanes.get(i).intersectionEntryPoint = ie;
	}

	//West road
	for (int i = 0; i < wRoad.lanes.size(); i++)
	{
		//Lanes start at the left of the screen and go across to the intersection
		Coordinate c = new Coordinate(0, intSct.getAnchor().y + i);

		//The spawn point is the anchor
		Coordinate s = new Coordinate(c);

		//The intersection entry point is the opposite end to the anchor
		Coordinate ie = new Coordinate(c);
                System.out.println(i);
		ie.x += (wRoad.lanes.get(i).length - 1);

		//Set the anchor, spawn point, and intersection entry point
		wRoad.lanes.get(i).anchor = c;
		wRoad.lanes.get(i).spawnPoint = s;
		wRoad.lanes.get(i).intersectionEntryPoint = ie;
	}

	//East road
	for (int i = 0; i < eRoad.lanes.size(); i++)
	{
		//Lanes start at the right of the intersection and go across to the right of the screen
		Coordinate c = new Coordinate(intSct.getAnchor().x + intSct.getWidth(),
                        intSct.getAnchor().y + i);

		//The spawn point is the opposite end to the anchor
		Coordinate s = new Coordinate(c);
		s.x += (eRoad.lanes.get(i).length - 1);

		//The intersection entry point is the anchor
		Coordinate ie = c;

		//Set the anchor, spawn point, and intersection entry point
		eRoad.lanes.get(i).anchor = c;
		eRoad.lanes.get(i).spawnPoint = s;
		eRoad.lanes.get(i).intersectionEntryPoint = ie;
	}

	//The tilemap's size is twice the lane length plus the width of the intersection
	int gridW = (Lane.DEFAULT_LENGTH * 2) + intSct.getWidth();
	int gridH = (Lane.DEFAULT_LENGTH * 2) + intSct.getHeight();

	//Generate the tile map
	map = new TileMap(gridW, gridH);

	//Set the direction for each square in the TileMap
        //For each lane of each road
	for (Road r:roads)
	{
            for (Lane currLane:r.lanes)
            {
                //These hold the coordinates we are filling
                Coordinate temp = new Coordinate(currLane.anchor);

                //For each square in the lane
                for (int i = 0; i < currLane.length; i++)
                {
                        //Set the direction in the TileMap
                        map.setTile(temp, currLane.direction);

                        //The next square's position is dependant on the direction we are setting
                        if (currLane.direction == Direction.NORTH || currLane.direction == Direction.SOUTH)
                                temp.y++;
                        else
                                temp.x++;
                }
            }
	}
    }
}
